#include "reg52.h"
#include "math.h"
#define ON 10
#define ADD 11
#define SUB 12
#define MUL 13
#define DIV 14
#define EQU 15
#define BLANK 10
#define ERROR 11
#define MINUS 12
sbit SPEAKER = P3 ^ 7;
long Result, VarTmp;
unsigned char code LED[] = {0xc0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0xff, 0x86, 0xbf};
unsigned char code KeyTable[] = {ON, 0, EQU, ADD, 1, 2, 3, SUB, 4, 5, 6, MUL, 7, 8, 9, DIV};
unsigned int DisplayNo, Operate, MS, DisplayBuffer[8];
bit Over, NoError = 1, FirstInput = 1;
unsigned int BeepTime;

void KeyProcess(unsigned int k);
void ModifyDisplayBuffer(VarTmp);
void ClrDisplayBuffer();
void Calculate();

void delayms(unsigned char i)
{
    MS = i;
    while (MS)
        ;
}
unsigned char Key()
{
    unsigned int Row, Col, k;
    P1 = 0x0f;
    k = P1 & 0x0f;
    if (k == 0x0f)
        return 0xff;
    delayms(20);
    k = P1 & 0x0f;
    if (k == 0x0f)
        return 0xff;
    BeepTime = 300;
    for (Row = 0; Row < 4; Row++)
    {
        P1 = 0x7f >> Row;
        k = P1 & 0x0f;
        if (k != 0x0f)
        {
            Col = 0;
            while (k & (1 << Col))
                Col++;
            break;
        }
    }
    while ((P1 & 0x0f) != 0x0f)
        ;
    k = Row + Col * 4;
    return KeyTable[k];
}

void KeyProcess(unsigned char k)
{
    if (k == ON)
    {
        Result = 0, VarTmp = 0, Operate = 0, Over = 0, NoError = 1, FirstInput = 1;
        ClrDisplayBuffer();
    }
    if (!NoError)
        return;
    if (k < 10)
    {
        if (Over)
            Over = 0, VarTmp = 0, Result = 0, Operate = 0, FirstInput = 1;
        VarTmp = VarTmp * 10 + k;
        if (VarTmp > 9999999)
            VarTmp = VarTmp / 10;
        if (Operate)
            FirstInput = 0;
        ModifyDisplayBuffer(VarTmp);
    }
    if (k > 10 && k < 15)
    {
        if (Over)
        {
            Over = 0, VarTmp = 0, FirstInput = 1, Operate = k;
            return;
        }
        if (Operate && FirstInput == 0)
        {
            Calculate();
            VarTmp = 0, FirstInput = 1;
        }
        if (Operate == 0)
        {
            Result = VarTmp;
            VarTmp = 0;
        }
        Operate = k;
    }
    if (k == EQU)
    {
        if (Operate && FirstInput == 0)
        {
            Calculate();
            Over = 1;
        }
    }
}

void ClrDisplayBuffer()
{
    unsigned char i;
    for (i = 0; i < 7; i++)
        DisplayBuffer[i] = BLANK;
    DisplayBuffer[7] = 0;
}
void ModifyDisplayBuffer(long num)
{
    unsigned char i;
    if (num > 9999999 || num < -9999999)
    {
        ClrDisplayBuffer();
        DisplayBuffer[0] = ERROR;
        NoError = 0;
        return;
    }
    ClrDisplayBuffer();
    if (num < 0)
    {
        num = labs(num);
        DisplayBuffer[0] = MINUS;
    }
    i = 7;
    do
    {
        DisplayBuffer[i] = num % 10;
        num /= 10;
        i--;
    } while (num != 0);
}

void Calculate()
{
    switch (Operate)
    {
    case ADD:
        Result = Result + VarTmp;
        ModifyDisplayBuffer(Result);
        break;

    case SUB:
        Result = Result - VarTmp;
        ModifyDisplayBuffer(Result);
        break;

    case MUL:
        Result = Result + VarTmp;
        ModifyDisplayBuffer(Result);
        break;

    case DIV:
        if (VarTmp != 0)
        {
            Result = Result / VarTmp;
            ModifyDisplayBuffer(Result);
        }
        else
        {
            ClrDisplayBuffer();
            DisplayBuffer[0] = ERROR;
            NoError = 0;
        }
        break;
    }
}

void main()
{
    unsigned char k;
    TMOD = 1;
    TR0 = 1;
    ET0 = 1;
    EA = 1;
    ClrDisplayBuffer();
    while (1)
    {
        k = Key();
        if (k != 0xff)
            KeyProcess(k);
    }
}

void Display() interrupt 1
{
    TL0 = 64536 % 256;
    TH0 = 64536 / 256;
    if (MS)
        MS--;
    if (BeepTime)
    {
        BeepTime--;
        SPEAKER = ~SPEAKER;
    }
    P2 = 0;
    P0 = LED[DisplayBuffer[DisplayNo]];
    P2 = 1 << DisplayNo;
    if (++DisplayNo == 8)
        DisplayNo = 0;
}